package com.huaxin.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaxin.device.dto.ResponseCode;
import com.huaxin.device.dto.ResponseResult;
import com.huaxin.device.dto.request.EquipmentDataSourceCreateReqDTO;
import com.huaxin.device.dto.request.EquipmentDataSourcePageListReqDTO;
import com.huaxin.device.mapper.EquipmentDataSourceMapper;
import com.huaxin.device.mapping.EquipmentDataSourceMapping;
import com.huaxin.device.models.EquipmentDataSource;
import com.huaxin.device.service.EquipmentDataSourceService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.webjars.NotFoundException;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static org.springframework.util.StringUtils.hasText;

@Service
@RequiredArgsConstructor
public class EquipmentDataSourceServiceImpl extends ServiceImpl<EquipmentDataSourceMapper, EquipmentDataSource> implements EquipmentDataSourceService {

    private final ApplicationContext applicationContext;
    private final EquipmentDataSourceMapping mapping;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> create(List<EquipmentDataSourceCreateReqDTO> in) {
        if (in == null || in.isEmpty()) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        if (!hasConsistentCollectorAndEquipment(in)) {
            return ResponseResult.failure(ResponseCode.BAD_REQUEST, "数据源关联的采集设备ID或被采集的电力设备ID不一致", null);
        }

        List<String> dataTypes = in.stream().map(EquipmentDataSourceCreateReqDTO::getDataType).toList();
        if (existsByTriplet(in.get(0).getCollectorId(), in.get(0).getEquipmentId(), dataTypes)) {
            return ResponseResult.failure(ResponseCode.BAD_REQUEST, "采集设备ID和被采集的电力设备ID已关联该数据类型", null);
        }

        List<EquipmentDataSource> entityList = mapping.toEntityList(in);
        if (!saveBatch(entityList)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "创建失败，请稍后再试！", null);
        }
        return ResponseResult.ok("创建成功");
    }

    /**
     * 判断列表中所有对象的 collectorId 和 equipmentId 是否分别一致
     * - 忽略 null 和 空字符串 ""
     * - 只要有一个不同，就返回 false
     */
    public static boolean hasConsistentCollectorAndEquipment(List<EquipmentDataSourceCreateReqDTO> list) {
        if (list == null || list.isEmpty()) {
            return true; // 空集合视为一致
        }

        // 提取非空 collectorId 并去重
        Set<String> collectors = list.stream()
                .map(dto -> cleanId(dto.getCollectorId()))
                .filter(id -> id != null && !id.isEmpty())
                .collect(Collectors.toSet());

        // 提取非空 equipmentId 并去重
        Set<String> equipments = list.stream()
                .map(dto -> cleanId(dto.getEquipmentId()))
                .filter(id -> id != null && !id.isEmpty())
                .collect(Collectors.toSet());

        // 如果去重后数量 <= 1，说明值都相同
        boolean collectorConsistent = collectors.size() <= 1;
        boolean equipmentConsistent = equipments.size() <= 1;

        return collectorConsistent && equipmentConsistent;
    }

    /**
     * 清理 ID：null 转空串，trim
     */
    private static String cleanId(String id) {
        return id == null ? null : id.trim();
    }

    private boolean existsByTriplet(String collectorId, String equipmentId, List<String> dataTypes) {
        LambdaQueryWrapper<EquipmentDataSource> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentDataSource::getCollectorId, collectorId);
        wrapper.eq(EquipmentDataSource::getEquipmentId, equipmentId);
        wrapper.in(EquipmentDataSource::getDataType, dataTypes);
        return exists(wrapper);
    }

    @Override
    public EquipmentDataSource getByDataSourceId(String id) {
        if (!hasText(id)) {
            throw new IllegalArgumentException("ID不能为空");
        }

        EquipmentDataSource entity = getById(id);
        if (entity == null) {
            throw new NotFoundException("数据源关联不存在");
        }
        return entity;
    }

    @Override
    public ResponseResult<String> delete(String id) {
        EquipmentDataSource entity = getByDataSourceId(id);

        boolean removed = this.applicationContext.getBean(EquipmentDataSourceService.class).removeById(id);
        if (!removed) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "删除失败，请稍后重试", null);
        }
        return ResponseResult.ok("删除成功！");
    }

    @Override
    public ResponseResult<IPage<EquipmentDataSource>> pageQuery(EquipmentDataSourcePageListReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        IPage<EquipmentDataSource> page = new Page<>(in.getPageNum(), in.getPageSize());
        LambdaQueryWrapper<EquipmentDataSource> wrapper = new LambdaQueryWrapper<>();

        if (hasText(in.getCollectorId())) {
            wrapper.eq(EquipmentDataSource::getCollectorId, in.getCollectorId());
        }
        if (hasText(in.getEquipmentId())) {
            wrapper.eq(EquipmentDataSource::getEquipmentId, in.getEquipmentId());
        }
        if (hasText(in.getRoomId())) {
            wrapper.eq(EquipmentDataSource::getRoomId, in.getRoomId());
        }
        if (hasText(in.getCabinetId())) {
            wrapper.eq(EquipmentDataSource::getCabinetId, in.getCabinetId());
        }
        if (hasText(in.getWellId())) {
            wrapper.eq(EquipmentDataSource::getWellId, in.getWellId());
        }
        if (hasText(in.getDataType())) {
            wrapper.eq(EquipmentDataSource::getDataType, in.getDataType());
        }
        if (in.getIsPrimary() != null) {
            wrapper.eq(EquipmentDataSource::getIsPrimary, in.getIsPrimary());
        }
        if (hasText(in.getOrgId())) {
            wrapper.eq(EquipmentDataSource::getOrgId, in.getOrgId());
        }
        if (hasText(in.getFamilyId())) {
            wrapper.like(EquipmentDataSource::getFamilyId, in.getFamilyId());
        }
        if (hasText(in.getKeyword())) {
            wrapper.and(wrapper1 ->
                    wrapper1.like(EquipmentDataSource::getDataName, in.getKeyword())
                            .or()
                            .like(EquipmentDataSource::getDescription, in.getKeyword()));
        }

        wrapper.orderByDesc(EquipmentDataSource::getCreatedAt);

        IPage<EquipmentDataSource> resultPage = page(page, wrapper);
        return ResponseResult.ok(resultPage);
    }

    @Override
    public List<EquipmentDataSource> getByCollectorId(String collectorId) {
        LambdaQueryWrapper<EquipmentDataSource> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentDataSource::getCollectorId, collectorId);
        return list(wrapper);
    }

    @Override
    public List<EquipmentDataSource> getByEquipmentId(String equipmentId) {
        LambdaQueryWrapper<EquipmentDataSource> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentDataSource::getEquipmentId, equipmentId);
        return list(wrapper);
    }

    @Override
    public ResponseResult<Boolean> toggleIsPrimary(String id) {
        EquipmentDataSource entity = getByDataSourceId(id);
        entity.setIsPrimary(!entity.getIsPrimary());
        return ResponseResult.ok(updateById(entity));
    }
}